<?php
/**
 * @since   2022-02-20
 * @author  zhaoxiang <zhaoxiang051405@gmail.com>
 */

namespace App\Controller\Admin;

use App\Constants\ErrorCode;
use App\Constants\RedisKey;
use App\Middleware\AdminMiddleware;
use App\Model\AdminApp;
use App\Model\AdminList;
use Hyperf\HttpServer\Annotation\Controller;
use Hyperf\HttpServer\Annotation\GetMapping;
use Hyperf\HttpServer\Annotation\Middleware;
use Hyperf\HttpServer\Annotation\PostMapping;
use Hyperf\Redis\Redis;
use Hyperf\Utils\ApplicationContext;
use Psr\Container\ContainerExceptionInterface;
use Psr\Container\NotFoundExceptionInterface;

#[Controller(prefix: '/admin/InterfaceList'), Middleware(AdminMiddleware::class)]
class InterfaceListController extends BaseController {

    /**
     * 获取接口列表
     * @return array
     * @author zhaoxiang <zhaoxiang051405@gmail.com>
     */
    #[GetMapping(path: 'index')]
    public function index(): array {
        $limit = $this->request->query('size', config('apiadmin.admin_list_default'));
        $type = $this->request->query('type', '');
        $keywords = $this->request->query('keywords', '');
        $status = $this->request->query('status', '');

        $obj = AdminList::query();
        if (strlen($status)) {
            $obj = $obj->where('status', $status);
        }
        if ($type) {
            switch ($type) {
                case 1:
                    $obj = $obj->where('hash', $keywords);
                    break;
                case 2:
                    $obj = $obj->where('info', 'like', "%{$keywords}%");
                    break;
                case 3:
                    $obj = $obj->where('api_class', 'like', "%{$keywords}%");
                    break;
            }
        }
        $listObj = $obj->orderByDesc('id')->paginate((int)$limit);

        return $this->buildSuccess([
            'list'  => $listObj->items(),
            'count' => $listObj->total()
        ]);
    }

    /**
     * 获取接口唯一标识
     * @author zhaoxiang <zhaoxiang051405@gmail.com>
     */
    #[GetMapping(path: 'getHash')]
    public function getHash(): array {
        $res['hash'] = uniqid('', false);

        return $this->buildSuccess($res);
    }

    #[PostMapping(path: 'add')]
    public function add(): array {
        $postData = $this->request->post();
        if (!preg_match("/^[A-Za-z0-9_\/]+$/", $postData['api_class'])) {
            return $this->buildFailed(ErrorCode::DB_SAVE_ERROR, '真实类名只允许填写字母，数字和/');
        }

        $postData = $this->filterData((new AdminList())->getTable(), $postData);
        $res = AdminList::insert($postData);
        if ($res === false) {
            return $this->buildFailed(ErrorCode::DB_SAVE_ERROR);
        }

        return $this->buildSuccess();
    }

    /**
     * 接口状态编辑
     * @return array
     * @throws ContainerExceptionInterface
     * @throws NotFoundExceptionInterface
     * @author zhaoxiang <zhaoxiang051405@gmail.com>
     */
    #[GetMapping(path: 'changeStatus')]
    public function changeStatus(): array {
        $hash = $this->request->query('hash');
        $status = $this->request->query('status');

        $info = AdminList::query()->where('hash', $hash)->first();

        if ($info) {
            $info->status = $status;
            $info->save();

            $redis = (ApplicationContext::getContainer())->get(Redis::class);
            $redis->del(RedisKey::API_INFO . ':' . $hash);
            $redis->del(RedisKey::API_INFO . ':' . $info->api_class);
        }

        return $this->buildSuccess();
    }

    /**
     * 编辑接口
     * @return array
     * @throws ContainerExceptionInterface
     * @throws NotFoundExceptionInterface
     * @author zhaoxiang <zhaoxiang051405@gmail.com>
     */
    #[PostMapping(path: 'edit')]
    public function edit(): array {
        $postData = $this->request->post();
        if (!preg_match("/^[A-Za-z0-9_\/]+$/", $postData['api_class'])) {
            return $this->buildFailed(ErrorCode::DB_SAVE_ERROR, '真实类名只允许填写字母，数字和/');
        }

        $postData = $this->filterData((new AdminList())->getTable(), $postData);
        AdminList::query()->where('id', $postData['id'])->update($postData);

        $redis = (ApplicationContext::getContainer())->get(Redis::class);
        $redis->del(RedisKey::API_INFO . ':' . $postData['hash']);
        $redis->del(RedisKey::API_INFO . ':' . $postData['api_class']);

        return $this->buildSuccess();
    }

    /**
     * 删除接口
     * @return array
     * @author zhaoxiang <zhaoxiang051405@gmail.com>
     */
    #[GetMapping(path: 'del')]
    public function del(): array {
        $hash = $this->request->query('hash');
        if (!$hash) {
            return $this->buildFailed(ErrorCode::EMPTY_PARAMS, '缺少必要参数');
        }

        $hashRule = AdminApp::query()->whereRaw('FIND_IN_SET(?, app_api)', [$hash])->get();
        if ($hashRule) {
            $oldInfo = AdminList::query()->where('hash', $hash)->first();
            foreach ($hashRule as $rule) {
                $appApiArr = explode(',', $rule->app_api);
                $appApiIndex = array_search($hash, $appApiArr);
                array_splice($appApiArr, $appApiIndex, 1);
                $rule->app_api = implode(',', $appApiArr);

                $appApiShowArrOld = json_decode($rule->app_api_show, true);
                $appApiShowArr = $appApiShowArrOld[$oldInfo->group_hash];
                $appApiShowIndex = array_search($hash, $appApiShowArr);
                array_splice($appApiShowArr, $appApiShowIndex, 1);
                $appApiShowArrOld[$oldInfo->group_hash] = $appApiShowArr;
                $rule->app_api_show = json_encode($appApiShowArrOld);

                $rule->save();
            }

            AdminList::query()->where('hash', $hash)->delete();
            AdminField::query()->where('hash', $hash)->delete();

            $redis = (ApplicationContext::getContainer())->get(Redis::class);
            $redis->del(RedisKey::API_INFO . ':' . $hash);
            $redis->del(RedisKey::API_INFO . ':' . $oldInfo->api_class);
        }

        return $this->buildSuccess();
    }

    /**
     * 刷新接口路由
     * @return array
     * @author zhaoxiang <zhaoxiang051405@gmail.com>
     * TODO::处理刷新
     */
    public function refresh(): array {
//        $rootPath = root_path();
//        $apiRoutePath = $rootPath . 'route/apiRoute.php';
//        $tplPath = $rootPath . 'install/apiRoute.tpl';
//        $methodArr = ['*', 'POST', 'GET'];
//
//        $tplOriginStr = file_get_contents($tplPath);
//        $listInfo = (new AdminList())->where('status', 1)->select();
//        $tplStr = [];
//        foreach ($listInfo as $value) {
//            if ($value['hash_type'] === 1) {
//                array_push($tplStr, 'Route::rule(\'' . addslashes($value->api_class) . '\',\'api.' . addslashes($value->api_class) . '\', \'' . $methodArr[$value->method] . '\')->middleware([app\middleware\ApiAuth::class, app\middleware\ApiPermission::class, app\middleware\RequestFilter::class, app\middleware\ApiLog::class]);');
//            } else {
//                array_push($tplStr, 'Route::rule(\'' . addslashes($value->hash) . '\',\'api.' . addslashes($value->api_class) . '\', \'' . $methodArr[$value->method] . '\')->middleware([app\middleware\ApiAuth::class, app\middleware\ApiPermission::class, app\middleware\RequestFilter::class, app\middleware\ApiLog::class]);');
//            }
//        }
//        $tplOriginStr = str_replace(['{$API_RULE}'], [implode(PHP_EOL . '    ', $tplStr)], $tplOriginStr);
//
//        file_put_contents($apiRoutePath, $tplOriginStr);

        return $this->buildSuccess();
    }

}
